package com.liangsui.mss.controller.doctor;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.liangsui.mss.aspectj.Log;
import com.liangsui.mss.aspectj.enums.BusinessType;
import com.liangsui.mss.component.alipay.AlipayConfig;
import com.liangsui.mss.component.alipay.PayService;
import com.liangsui.mss.constants.Constants;
import com.liangsui.mss.domain.*;
import com.liangsui.mss.dto.OrderChargeDto;
import com.liangsui.mss.dto.OrderChargeFromDto;
import com.liangsui.mss.dto.OrderChargeItemDto;
import com.liangsui.mss.service.CareService;
import com.liangsui.mss.service.OrderChargeService;
import com.liangsui.mss.utils.IdGeneratorSnowflake;
import com.liangsui.mss.utils.ShiroSecurityUtils;
import com.liangsui.mss.vo.AjaxResult;
import com.liangsui.mss.vo.DataGridView;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.*;

/**
 * OrderChargeController
 *
 * @author zhangjiawei
 * @email 1533167396@qq.com
 * @date 2022/12/8 14:52
 */
@RestController
@RequestMapping("doctor/charge")
public class OrderChargeController {

    /**
     * @功能描述:远程调用
     * @Description:处方、病例、开诊$
     */
    @DubboReference
    private CareService careService;

    /**
     * @功能描述:远程调用收费接口
     * @Description:增删改
     */
    @DubboReference
    private OrderChargeService orderChargeService;

    /**
     * @功能描述:根据挂号ID查询未支付的处方信息及详情
     * @Description:根据病例ID查询处方信息
     */
    @GetMapping("getNoChargeCareHistoryByRegId/{regId}")
    public AjaxResult getNoChargeCareHistoryByRegId(@PathVariable(value = "regId") String regId) {
        // 声明返回的json类型
        /*
         * data:{
         * 	careHistory:{....}  	object
         * 	careOrders:[{  object []
         *     ......
         * 	  "careOrderItems":[{
         * 	  	......
         * 	  }]
         *   }]
         * }
         * */
        Map<String, Object> res = new HashMap<>();
        // 根据挂号ID查询病例信息
        System.err.println(regId);
        CareHistory careHistory = this.careService.queryCareHistoryByRegId(regId);
        if (null == careHistory) {
            return AjaxResult.fail("【" + regId + "】 该挂号单没有对应的病例信息,请核对后再次查询");
        }

        // 组装数据 存放默认参数
        // 病例信息
        res.put("careHistory", careHistory);
        // 处方信息
        res.put("careOrders", Collections.EMPTY_LIST);
        // 声明一个 可以 存放  careOrder的集合
        List<Map<String, Object>> mapList = new ArrayList<>();
        // 根据病例编号查询 处方信息 和 处方详细信息
        List<CareOrder> careOrders = this.careService.queryCareOrdersByChId(careHistory.getChId());
        if (careOrders.isEmpty()) {
            return AjaxResult.fail("【" + regId + "】 该挂号单没有相关的处方信息,请核对后再次查询");
        }

        // 组装 处方详细信息
        for (CareOrder careOrder : careOrders) {
            // 将对象转换为 map
            Map<String, Object> beanToMap = BeanUtil.beanToMap(careOrder);
            // 定义一个 默认的处方详细
            beanToMap.put("careOrderItems", Collections.EMPTY_LIST);
            BigDecimal bigDecimal = new BigDecimal("0");
            // 根据处方信息 查询 未支付的 处方详细信息
            List<CareOrderItem> careOrderItems = this.careService.queryCareOrdersItemsByCoId(careOrder.getCoId(), Constants.ORDER_DETAILS_STATUS_0);

            // 如果当前的未支付处方详细为空 就 跳过当前循环
            if (careOrderItems.isEmpty()) {
                continue; // 不进行注入到前端页面当中
            } else {
                // 重新计算处方的总价 返回给前端
                for (CareOrderItem careOrderItem : careOrderItems) {
                    bigDecimal = bigDecimal.add(careOrderItem.getAmount());
                }
                // 组装完整数据
                beanToMap.put("careOrderItems", careOrderItems);
                // 组装完整的处方信息
                /*
                 * 	careOrders:[{  object []
                 *     ......
                 * 	  "careOrderItems":[{
                 * 	  	......
                 * 	  }]
                 * */
                mapList.add(beanToMap);
            }

        }
        // 如果没有 未支付的 处方信息
        if (mapList.isEmpty()) {
            return AjaxResult.fail("【" + regId + "】 该挂号单没有未支付的处方信息,请核对后再次查询");
        } else {
            // 放入处方
            res.put("careOrders", mapList);
            return AjaxResult.success("查询成功", res);
        }
    }

    /**
     * @功能描述:现金支付
     * @Description:分别把订单添加到收费表和支付订单详情表并且修改处方详情项目状态为支付完毕
     */
    @PostMapping("createOrderChargeWithCash")
    @Log(title = "现金支付", businessType = BusinessType.INSERT)
    public AjaxResult createOrderChargeWithCash(@RequestBody @Validated OrderChargeFromDto orderChargeFromDto) {
        try {
            // 1. 保存订单
            // 1.1 设置支付类型
            orderChargeFromDto.getOrderChargeDto().setPayType(Constants.PAY_TYPE_0);
            // 1.2 获取用户信息
            orderChargeFromDto.setSimpleUser(ShiroSecurityUtils.getCurrentSimpleUser());
            // 1.3 雪花算法设置订单ID
            String orderId = IdGeneratorSnowflake.generatorIdWithProfix(Constants.ID_PREFIX_ODC);
            orderChargeFromDto.getOrderChargeDto().setOrderId(orderId);
            // 1.3 进行保存
            this.orderChargeService.saveOrderAndItems(orderChargeFromDto);
            // 2. 因为是现金支付 所以只需要更新详情状态
            this.orderChargeService.paySuccess(orderId, null);
            return AjaxResult.success("现金支付成功");
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("现金支付失败");
        }
    }

    /**
     * 保存处方订单到 收费库和收费详情库当中
     *
     * @功能描述:创建支付包收费订单【预下单--生成二维码】
     * @Description:
     */
    @PostMapping("createOrderChargeWithzfb")
    @Log(title = "创建支付宝收费订单--预下单--生成二维码", businessType = BusinessType.INSERT)
    public AjaxResult createOrderChargeWithzfb(@RequestBody @Validated OrderChargeFromDto orderChargeFromDto) {
        // 1. 保存订单
        // 1.1 设置支付类型
        orderChargeFromDto.getOrderChargeDto().setPayType(Constants.PAY_TYPE_1);
        // 1.2 获取用户信息
        orderChargeFromDto.setSimpleUser(ShiroSecurityUtils.getCurrentSimpleUser());
        // 1.3 雪花算法设置订单ID
        String orderId = IdGeneratorSnowflake.generatorIdWithProfix(Constants.ID_PREFIX_ODC);
        orderChargeFromDto.getOrderChargeDto().setOrderId(orderId);
        // 1.3 进行保存
        this.orderChargeService.saveOrderAndItems(orderChargeFromDto);
        /**************************************创建支付宝开始**********************************************/
        // 交易订单 唯一
        String outTradeNo = orderId;
        // 交易所属
        String subject = "医疗服务系统";
        // 交易总金额
        String totalAmount = orderChargeFromDto.getOrderChargeDto().getOrderAmount().toString();
        // 折扣
        //String undiscountableAmount = null;
        // 组装订单详情说明
        String body = ""; // 说明
        List<OrderChargeItemDto> orderChargeItemDtoList = orderChargeFromDto.getOrderChargeItemDtoList();
        for (OrderChargeItemDto orderChargeItemDto : orderChargeItemDtoList) {
            body += orderChargeItemDto.getItemName() + "，" + orderChargeItemDto.getItemPrice() + "  ";
        }
        // 回调 + 订单号
        String notifyUrl = AlipayConfig.notifyUrl + outTradeNo;
        // 执行支付
        Map<String, Object> pay = PayService.pay(outTradeNo, subject, totalAmount, totalAmount, body, notifyUrl);
        String qrCode = pay.get("qrCode").toString();
        if (StringUtils.isNotBlank(qrCode)) {
            // 创建预订单 数据返回前端进行显示二维码
            Map<String, Object> map = new HashMap<>();
            map.put("orderId", orderId);
            map.put("allAmount", totalAmount);
            map.put("payUrl", qrCode);
            return AjaxResult.success(map);
        } else {
            return AjaxResult.fail(pay.get("msg").toString());
        }
        /**************************************创建支付宝结束**********************************************/
    }


    /**
     * @功能描述:根据订单ID查询订单信息【验证是否支付成功】
     * @Description:
     */
    @GetMapping("queryOrderChargeOrderId/{orderId}")
    public AjaxResult queryOrderChargeOrderId(@PathVariable String orderId) {
        OrderCharge orderCharge = this.orderChargeService.queryOrderChargeByOrderId(orderId);
        if (null == orderCharge) {
            // 订单不存在
            return AjaxResult.fail("【" + orderId + "】订单号所在的订单不存在,请核对后再次操作");
        }
        // 不是 支付宝 支付类型
        if (!orderCharge.getPayType().equals(Constants.PAY_TYPE_1)) {
            return AjaxResult.fail("【" + orderId + "】订单号所在的订单不是支付宝支付,请核对后再次操作");
        }
        return AjaxResult.success(orderCharge);
    }


    /**
     * @param orderChargeDto
     * @功能描述:分页查询所有收费单
     * @Description:模糊查询参数：患者名称、订单ID查询
     */
    @GetMapping("queryAllOrderChargeForPage")
    public AjaxResult queryAllOrderChargeForPage(OrderChargeDto orderChargeDto) {
        DataGridView dataGridView = this.orderChargeService.queryAllOrderChargeForPage(orderChargeDto);
        return AjaxResult.success("查询成功", dataGridView.getData(), dataGridView.getTotal());
    }

    /**
     * @功能描述:根据收费单的ID查询收费详情信息
     * @Description:查看详情根据订单ID
     */
    @GetMapping("queryOrderChargeItemByOrderId/{orderId}")
    public AjaxResult queryOrderChargeItemByOrderId(@PathVariable String orderId) {
        List<OrderChargeItem> orderChargeItemList = this.orderChargeService.queryOrderChargeItemByOrderId(orderId);
        return AjaxResult.success("查询成功", orderChargeItemList);
    }

    /**
     * @功能描述:订单列表现金支付订单
     * @Description:参数--订单ID
     */
    @PostMapping("payWithCash/{orderId}")
    public AjaxResult payWithCash(@PathVariable String orderId) {
        OrderCharge orderCharge = this.orderChargeService.queryOrderChargeByOrderId(orderId);
        if (null == orderCharge) {
            // 订单不存在
            return AjaxResult.fail("【" + orderId + "】订单号所在的订单不存在,请核对后再次操作");
        }
        // 如果已经支付过了 就无须再次
        if (orderCharge.getOrderStatus().equals(Constants.ORDER_STATUS_1)) {
            return AjaxResult.fail("【" + orderId + "】改订单已支付完成，无需再次支付,请核对后再次操作");
        }
        // 支付
        this.orderChargeService.paySuccess(orderId, null);
        return AjaxResult.success();
    }

    /**
     * @功能描述:订单列表里再次使用支付宝支付
     * @Description:根据订单ID来进行支付原来没有支付成功的订单(也就是待支付)
     */
    @PostMapping("toPayOrderWithZfb/{orderId}")
    public AjaxResult toPayOrderWithZfb(@PathVariable String orderId) {
        OrderCharge orderCharge = this.orderChargeService.queryOrderChargeByOrderId(orderId);
        if (null == orderCharge) {
            // 订单不存在
            return AjaxResult.fail("【" + orderId + "】订单号所在的订单不存在,请核对后再次操作");
        }
        // 如果已经支付过了 就无须再次
        if (orderCharge.getOrderStatus().equals(Constants.ORDER_STATUS_1)) {
            return AjaxResult.fail("【" + orderId + "】改订单已支付完成，无需再次支付,请核对后再次操作");
        }

        // 思路： 如果用户第一次是现金支付但是没有支付成功，就使用支付宝支付
        // 现金转支付宝   支付宝转现金

        /**************************************创建支付宝开始**********************************************/
        // 交易订单 唯一
        String outTradeNo = orderId;
        // 交易所属
        String subject = "医疗服务系统";
        // 交易总金额
        String totalAmount = orderCharge.getOrderAmount().toString();
        // 折扣
        //String undiscountableAmount = null;
        // 回调 + 订单号
        String notifyUrl = AlipayConfig.notifyUrl + outTradeNo;
        // 执行支付
        Map<String, Object> pay = PayService.pay(outTradeNo, subject, totalAmount, totalAmount, "", notifyUrl);
        String qrCode = pay.get("qrCode").toString();
        if (StringUtils.isNotBlank(qrCode)) {
            // 创建预订单 数据返回前端进行显示二维码
            Map<String, Object> map = new HashMap<>();
            map.put("orderId", orderId);
            map.put("allAmount", totalAmount);
            map.put("payUrl", qrCode);
            return AjaxResult.success(map);
        } else {
            return AjaxResult.fail(pay.get("msg").toString());
        }
        /**************************************创建支付宝结束**********************************************/
    }
}
